#!/usr/bin/ruby
# -*- ruby -*-
#
# http://www.reddit.com/r/dailyprogrammer/comments/178vsz/012513_challenge_118_hard_alphabetizing_cipher/
#
# Not a real solution, just funsies.

def debug(msg = "")
    puts "[DEBUG] #{msg.inspect.to_s}"
end

class Cipher
    attr_reader :m, :r
    def initialize(sequence)
        @m = ('a' .. 'z').to_a.zip(sequence).inject({}) do |r, (p, c)|
            r.merge(p => c)
        end

        @r = @m.invert
    end

    def encrypt(word)
        return word.split(//).map { |c| @m[c] || c }.join("")
    end

    def decrypt(word)
        return word.split(//).map { |c| @r[c] || c }.join("")
    end
end

class Ciphers
    include Enumerable

    LETTERS = "abcdefghijklmnopqrstuvwxyz".split(//)

    def each(to_take_from = LETTERS, taken = [], &blk)
        if to_take_from.empty?
            yield taken
        else
            to_take_from.each_index do |ind|
                item = to_take_from[ind]

                copy = to_take_from.clone
                copy.delete_at(ind)

                acc = taken.clone
                acc << item

                each(copy, acc, &blk)
            end
        end
    end

    def to_a(size)
        acc = []

        self.each do |c|
            acc << c

            size -= 1

            break unless size > 0
        end

        return acc
    end
end

class Mapper
    attr_reader :cipher

    def initialize(cipher)
        @cipher = cipher
    end

    def m(i)
        return @cipher.encrypt(i)
    end
end

class Reducer
    def r(r)
        a = r.split(//)

        return (a.sort == a) ? 1 : 0
    end
end

class Connecter
    def initialize(mapper, reducer, input)
        @mapper  = mapper
        @reducer = reducer
        @input   = input
    end

    def run
        return @input.inject(0) do |r, i|
            r + @reducer.r(@mapper.m(i))
        end
    end
end

seq = ARGV.first || "jfbqpwcvuamozhilgrxtkndesy"

c = Cipher.new(seq.split(//))

wl = File.new(File.basename($0).gsub(/\.rb$/, '.input')).readlines.map { |w| w.strip }

puts Connecter.new(Mapper.new(c), Reducer.new, wl).run
